/**
 * 
 */
package fr.cephb.joperon.webapp;


import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;

import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.TreeSet;

import java.util.Set;






import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


import com.oreilly.servlet.MultipartRequest;
import com.sleepycat.db.DatabaseException;


import fr.cephb.joperon.core.Mode;
import fr.cephb.joperon.core.Operon;
import fr.cephb.joperon.core.Ymd;
import fr.cephb.joperon.core.bio.Assembly;
import fr.cephb.joperon.core.db.PrjMgrDB;
import fr.cephb.joperon.core.entities.MPanel;
import fr.cephb.joperon.core.entities.PrjDna;
import fr.cephb.joperon.core.entities.PrjFin;
import fr.cephb.joperon.core.entities.PrjMgr;
import fr.cephb.joperon.core.entities.PrjSnp;
import fr.cephb.joperon.core.iterator.DatabaseValueIterator;

import fr.cephb.joperon.tool.OperonFactory;
import fr.cephb.joperon.tool.altera.Altera;
import fr.cephb.joperon.tool.createprj.CreatePrjFin;
import fr.cephb.joperon.tool.spindle.Spindle;
import fr.cephb.joperon.webapp.jpa.Access;
import fr.cephb.joperon.webapp.jpa.User;
import fr.cephb.util.Cast;


/**
 * The main controler for the operon Servlet
 * redirects the queries to the correct actions
 *
 */
public class JOperonController extends
	AbstractOperonServlet
	{
	private static final long serialVersionUID = 1L;
	private String defaultUserLogin=null;
	
    
	@Override
	public void init() throws ServletException
		{
		super.init();
		String s= getInitParameter("DEFAULT_USER_PROFILE");
		if(s!=null && s.trim().length()>0)
			{
			this.defaultUserLogin=s;
			}
		
		}
	
	
	@Override
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException
		{
		/** get current user */
		HttpSession session= req.getSession();
		User user= User.class.cast(session.getAttribute("operon_user"));
		MultipartRequest multipartRequest=null;
		
		if(session.isNew() || user==null)
			{
			if(this.defaultUserLogin!=null)
				{
				user= User.class.cast(getTopLink().createNamedQuery("user.byLogin").setParameter("login", this.defaultUserLogin).getSingleResult());
				
				}
			else
				{
				user= User.class.cast(getTopLink().createNamedQuery("user.anonymous").getSingleResult());
				
				}
			if(user==null) throw new NullPointerException("user is null");
			session.setAttribute("operon_user",user);
			}
		req.setAttribute("operon_user", user);
		if(req.getContentType()!=null && req.getContentType().contains("multipart/form-data"))
			{
			multipartRequest= new MultipartRequest(req,getWebTmpDir());
			}
		
		
		
		
		Operon operon=null;
		OperonFactory factory=null;
		String act= (multipartRequest==null?req.getParameter("act"):multipartRequest.getParameter("act"));
		String as=(multipartRequest==null?req.getParameter("as"):multipartRequest.getParameter("as"));
		Assembly assembly= (as==null|| !Cast.Integer.isA(as)?null:Assembly.getAssemblyById(Cast.Integer.cast(as)));
		if(assembly==null) assembly = Assembly.getDefaultAssembly();
		
		
		try
			{
			operon= Operon.newInstance(getDBHome());
			factory= new OperonFactory(operon);
			factory.setAssembly(assembly);
			req.setAttribute("operon", operon);
			req.setAttribute("operonFactory", factory);
			req.setAttribute("assembly", assembly);
			
			debug(act);
			if("users".equals(act))
				{
				req.setAttribute("users", getTopLink().createNamedQuery("user.all").getResultList());
				RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/users.jsp");
				dispatcher.forward(req, resp);
				}
			else if("user-edit".equals(act))
				{
				String id= req.getParameter("id");
				if(isEmpty(id)) throw new ServletException("id missing");
				if(!user.isRoot() && (
				   user.isAnonymous() ||
				   !String.valueOf(user.getId()).equals(id)))
				   {
				   throw new ServletException("Access denied");
				   };
				User other= null;
				try {
					other= getTopLink().find(User.class, Integer.parseInt(id));
					if(other==null)  throw new ServletException("User does not exists");
					req.setAttribute("user", other);
					Set<PrjMgr> prjmgr= new TreeSet<PrjMgr>();
					for(Access ac:other.getAccess())
						{
						PrjMgr proj=factory.getPrjMgr().get(ac.getProject());
						if(proj!=null) prjmgr.add(proj);
						}
					req.setAttribute("projects", prjmgr);
					
					RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/user-edit.jsp");
					dispatcher.forward(req, resp);
					} catch (Exception e) {
					throw new ServletException(e);
					}
				}
			else if("login".equals(act))
				{
				String login =  req.getParameter("login");
				if(isEmpty(login))
					{
					req.setAttribute("message", "Login is empty");
					RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/login.jsp");
					dispatcher.forward(req, resp);
					return;
					}
				String password =  req.getParameter("password");
				if(password==null)//password length can be empty
					{
					req.setAttribute("message", "Password is missing");
					RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/login.jsp");
					dispatcher.forward(req, resp);
					return;
					}
				user = getUserByLoginPassword(login,password);
				if(user==null)
					{
					req.setAttribute("message", "Wrong login/password");
					RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/login.jsp");
					dispatcher.forward(req, resp);
					return;
					}
				session.setAttribute("operon_user",user);
				RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/index.jsp");
				dispatcher.forward(req, resp);
				}
			else if("logout".equals(act))
				{
				session.invalidate();
				RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/login.jsp");
				dispatcher.forward(req, resp);
				}
			else if("user-new".equals(act))
				{
				String path ="WEB-INF/jsp/user-new.jsp";
				
				if(req.getParameter("step")!=null)
					{
					boolean ok=true;
					
					String login= req.getParameter("login");
					if(login==null) login="";
					login=login.trim();
					
					if(login.length()==0)
						{
						req.setAttribute("message", "Login is empty");
						ok=false;
						}
				
					if(ok && !"POST".equals(req.getMethod()))
						{
						req.setAttribute("message", "Bad Method");
						ok=false;
						}
					
					if(ok && login.length()>20)
						{
						req.setAttribute("message", "Login is too large");
						ok=false;
						}
				
					if(ok && !getTopLink().createNamedQuery("user.byLogin").setParameter("login", login).getResultList().isEmpty())
						{
						req.setAttribute("message", "Login already exists");
						ok=false;
						}
					
					String password[]=new String[]{
							req.getParameter("password1"),
							req.getParameter("password2")
						};
					
					for(int i=0;ok && i<2;++i)
						{
						if(password[i]==null) password[i]="";
						if(password[i].length()==0)
							{
							req.setAttribute("message", "Password is empty");
							ok=false;
							}
						password[i]=sha1(password[i]);
						}
					
					if(ok && !password[0].equals(password[1]))
						{
						req.setAttribute("message", "Passwords are not the same");
						ok=false;
						}
					
					if(ok)
						{
					
					
						 getUserTransaction().begin();
						try {
							User newuser= new User();
							newuser.setLogin(login);
							newuser.setSha1Password(password[0]);
							getTopLink().persist(newuser);
							getUserTransaction().commit();
							req.setAttribute("message", "New user was created.");
							path="WEB-INF/jsp/users.jsp";
							} 
						catch (Exception e)
							{
							e.printStackTrace();
							//utx.rollback();
							req.setAttribute("message", "Rollback. Error:"+e.getMessage());
							ok=false;
							}
						
							
						}
					}
		
				RequestDispatcher dispatcher = req.getRequestDispatcher(path);
				dispatcher.forward(req, resp);
				
				}
			else if("logout".equals(act))
				{
				session.invalidate();
				req.setAttribute("message", "Logged Off");
				RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/index.jsp");
				dispatcher.forward(req, resp);
				}
			else if("groups".equals(act))
				{
				RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/groups.jsp");
				dispatcher.forward(req, resp);
				}
			else if("prjmgr-list".equals(act))
				{
				req.setAttribute("projects", factory.getPrjMgr().getValues());
				RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/prjmgr-list.jsp");
				dispatcher.forward(req, resp);
				}
			else if("prjmgr-new".equals(act))
				{
				if(req.getParameter("step")!=null)
					{
					boolean ok=true;
					
					
					if(user.isAnonymous())
						{
						req.setAttribute("message", "No Privilege to create a Project");
						ok=false;
						}
		
					
					String pid= req.getParameter("pid");
					if(pid==null) pid="";
					pid=pid.trim().toUpperCase();
					
					String def= req.getParameter("def");
					if(def==null) def="";
					def=def.trim();
					
					
					if(ok && isEmpty(pid))
						{
						req.setAttribute("message", "Name is empty");
						ok=false;
						}
					
					if(ok && isEmpty(def))
						{
						req.setAttribute("message", "Definition is empty");
						ok=false;
						}	
					
					if(ok && !"POST".equals(req.getMethod()))
						{
						req.setAttribute("message", "Bad Method");
						ok=false;
						}
					
					if(ok && factory.getPrjMgr().containsKey(pid))
						{
						req.setAttribute("message", "Project Already Exists");
						ok=false;
						}
					
					if(ok)
						{
						factory.safeClosePrjMgr();
						PrjMgr mgr= new PrjMgr();
						mgr.setDef(def);
						mgr.setLog(user.getLogin());
						mgr.setPid(pid);
						mgr.setYmd(Ymd.now());
						
						Operon writer=null;
						PrjMgrDB db=null;
						try {
							writer=  Operon.newInstance(getDBHome(),Mode.WRITE);
							db= new PrjMgrDB(writer);
							db.open();
							db.put(mgr.getPid(), mgr);
							
							
							getUserTransaction().begin();
							try {
								Access access= new Access();
								access.setUser(user);
								access.setProject(pid);
								access.setAdministrator(true);
								access.setWriter(true);
								getTopLink().persist(access);
								getUserTransaction().commit();
								} 
							catch (Exception e)
								{
								//cannot rollback berkeley
								e.printStackTrace();
								}
							
							resp.sendRedirect(req.getContextPath()+"/operon?act=prjmgr-edit&id="+URLEncoder.encode(pid,"UTF-8"));
							return;
							} 
						catch (Exception e) 
							{
							System.err.println("K");
							ok=false;
							throw new ServletException(e);
							}
						finally
							{
							System.err.println("L");
							if(db!=null) db.safeClose();
							if(writer!=null) writer.safeClose();
							}
						
						}
					}
				
				RequestDispatcher dispatcher = req.getRequestDispatcher(
					"WEB-INF/jsp/prjmgr-new.jsp");
				dispatcher.forward(req, resp);
				}
			else if("prjdna-edit".equals(act))
				{
				String pid=req.getParameter("pid");
				if(isEmpty(pid)) throw new ServletException("pid is missing");
				if(!user.canReadProject(pid)) throw new ServletException("Access denied");
				String fix=req.getParameter("fix");
				if(isEmpty(fix)) throw new ServletException("fix is missing");
				if(!fix.startsWith("D") ) throw new ServletException("Not a D fin");
				PrjFin prjfin= factory.getPrjFin().findByFix(pid,fix);
				if(prjfin==null) throw new ServletException("Not Found");
				PrjDna prjdna= factory.getPrjDna().get(prjfin.getProjCode());
				if(prjdna==null) throw new ServletException("Not Found");
				
				
				resp.setContentType("text/plain");
				PrintWriter out= resp.getWriter();
				for(String dna:prjdna.getItems())
					{
					out.println(dna);
					}
				out.flush();
				}
			else if("prjsnp-edit".equals(act))
				{
				String pid=req.getParameter("pid");
				if(isEmpty(pid)) throw new ServletException("pid is missing");
				if(!user.canReadProject(pid)) throw new ServletException("Access denied");
				String fix=req.getParameter("fix");
				if(isEmpty(fix)) throw new ServletException("fix is missing");
				if(!fix.startsWith("S") ) throw new ServletException("Not A SNP fin");
				PrjFin prjfin= factory.getPrjFin().findByFix(pid,fix);
				if(prjfin==null) throw new ServletException("Not Found");
				if(prjfin.getAssembly()==null) throw new ServletException("Assembly Not Found");
				
				
				
				resp.setContentType("text/plain");
				PrintWriter out= resp.getWriter();
				
				DatabaseValueIterator<PrjSnp> iter=null;
				try {
					iter=factory.getPrjSnp(prjfin.getAssembly()).listValues(pid+"_"+fix);
					while(iter.hasNext())
						{
						PrjSnp smp=iter.next();
						out.print(smp.getAcn());
						out.print('\t');
						out.print(smp.getFin());
						out.print('\t');
						out.print(smp.getFid().getChromosome());
						out.print('\t');
						out.print(smp.getFid().getPosition());
						out.println();
						}
				} catch (Exception e) {
					throw new ServletException(e);
				}finally
					{
					if(iter!=null) iter.close();
					}
				}
			else if("prjmgr-edit".equals(act))
				{
				boolean ok=true;
				String pid= req.getParameter("id");
				String view= req.getParameter("view");
				PrjMgr project=null;
				if(isEmpty(pid))
					{
					req.setAttribute("message", "id undefined");
					ok=false;
					}
				else
					{
					project =factory.getPrjMgr().get(pid);
					}
				
				if(ok && project==null)
					{
					req.setAttribute("message", "project does not exists");
					ok=false;
					}
				if(ok && !user.canReadProject(pid))
					{
					req.setAttribute("message", "user cannot read that project");
					ok=false;
					}
				
				if(!ok)
					{
					RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/prjmgr-list.jsp");
					dispatcher.forward(req, resp);
					}
				else
					{
					req.setAttribute("project",project);
					if("users".equals(view))
						{
						req.setAttribute("users", getTopLink().createNamedQuery("access.users.byProject").setParameter("project", pid).getResultList());
						}
					else if(view==null || "prjfins".equals(view))
						{
						req.setAttribute("prjfins",factory.getPrjFin().get(pid));
						}
					RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/prjmgr-edit.jsp");
					dispatcher.forward(req, resp);
					}
				
				}
			else if("prjfin-new".equals(act))
				{
				boolean ok=true;

				if(multipartRequest==null) throw new ServletException("not a mulitpart request");
				CreatePrjFin subapp= new CreatePrjFin();
				subapp.setTarget(PrjFin.Target.SNP);
				subapp.setUser(user);
				
				File file=multipartRequest.getFile("file");
				if(ok && file==null)
					{
					ok=false;
					req.setAttribute("message", "No File was uploaded");
					}
				subapp.setInputFile(file);
				
				String pid= multipartRequest.getParameter("project-id");
				if(ok && isEmpty(pid))
					{
					req.setAttribute("message", "project-id undefined");
					ok=false;
					}
				subapp.setProjectId(pid);
				
				
				String def= multipartRequest.getParameter("def");
				if(ok && isEmpty(def))
					{
					req.setAttribute("message", "project def missing");
					ok=false;
					}
				subapp.setDef(def);
				
				
				if(ok && multipartRequest.getParameter("as")==null)
					{
					req.setAttribute("message", "assembly is missing");
					ok=false;
					}
				else
					{
					subapp.setAssembly(assembly);
					}
			
				
				
				if(ok)
					{
					factory.close();
					Operon writer=null;
					OperonFactory wFact=null;
					try {
						writer=  Operon.newInstance(getDBHome(),Mode.WRITE);
						wFact= new OperonFactory(writer);
						subapp.setFactory(wFact);
						
						subapp.build();	
						req.setAttribute("message", "prjfin was created");
						RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/prjmgr-list.jsp");
						dispatcher.forward(req, resp);
						return;
						}
					catch (Exception e) 
						{
						debug(e);
						ok=false;
						throw new ServletException(e);
						}
					finally
						{
						if(wFact!=null) wFact.close();
						if(writer!=null) writer.safeClose();
						file.delete();
						}
					}
				if(file!=null && file.exists()) file.delete();
				RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/prjmgr-list.jsp");
				dispatcher.forward(req, resp);
				return;
				}
			else if("about-snp".equals(act))
				{
				Integer step= Cast.Integer.cast( multipartRequest==null?req.getParameter("step"):multipartRequest.getParameter("step"));
				
				debug(""+step+"  "+ (multipartRequest==null?req.getParameter("step"):multipartRequest.getParameter("step")));
				if(step==null || multipartRequest==null)
					{
					debug();
					//show default interface
					req.setAttribute("assemblies",Assembly.getAssemblies());
					RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/about-snp.jsp");
					dispatcher.forward(req, resp);
					return;
					}
				
				if( step>4 || step<0)
					{
					throw new ServletException("bad input");
					}
					
				//assemblies
				Set<Assembly> assemblies=new HashSet<Assembly>();
				for(String build: arrayNotNull(multipartRequest.getParameterValues("as")))
					{
					if(!Cast.Integer.isA(build)) continue;
					Assembly tmp= Assembly.getAssemblyById(Cast.Integer.cast(build));
					if(tmp==null) continue;
					assemblies.add(tmp);
					}
				req.setAttribute("assemblies",assemblies);
				
				//mPanel
				Set<MPanel> mpanels=  new HashSet<MPanel>();
				if(step==0 )
					{
					mpanels.addAll(factory.getMPanel().getValues());
					}
				else
					{
					for(String mpanel: arrayNotNull(multipartRequest.getParameterValues("mpanel")))
						{
						if(!Cast.Integer.isA(mpanel)) continue;
						MPanel mpane= factory.getMPanel().get(Cast.Integer.cast(mpanel));
						if(mpane==null) continue;
						mpanels.add(mpane);
						}
					}
				req.setAttribute("mpanels",mpanels);
				
				//formats
				Set<String> formats= new HashSet<String>();
				if(step<5)
					{
					for(String fmt: arrayNotNull(multipartRequest.getParameterValues("fmt")))
						{
						formats.add(fmt);
						}
					}
				req.setAttribute("fmts",formats);
				
				
				//genotypes de souris
				List<PrjFin> prjfin4dnas = getPrjFinForUser(user, factory, PrjFin.Target.DNA,assemblies);
				if(step>2)
					{
					int k=0;
					while(k< prjfin4dnas.size())
						{
						boolean keep=false;
						for(String projcode: arrayNotNull(multipartRequest.getParameterValues("prjfin4dna")))
							{
							if(prjfin4dnas.get(k).getProjCode().equals(projcode))
								{
								keep=true;
								break;
								}
							}
						if(keep)
							{
							k++;
							}
						else
							{
							prjfin4dnas.remove(k);
							}
						}
					}
				req.setAttribute("prjfin4dnas",prjfin4dnas);
				
				
				if(step==3)
					{
					req.setAttribute("prjfins",getPrjFinForUser(user, factory, PrjFin.Target.SNP));
					}
				
				if(step==4)
					{
					Set<String> prjdnasIds = new HashSet<String>();
					for(PrjFin prjfin: prjfin4dnas)
						{
						if(!factory.getPrjDna().containsKey(prjfin.getProjCode()))
							{
							continue;
							}
						prjdnasIds.add(prjfin.getProjCode());
						}
					
					
					super.runSnpInfo(
							multipartRequest, 
							resp,
							factory,
							user,
							assemblies,
							mpanels,
							prjdnasIds,
							formats
							);
					return;
					}
				else
					{
					req.setAttribute("step",String.valueOf(step));
					RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/about-snp.jsp");
					dispatcher.forward(req, resp);
					return;
					}
				
				}
			else if("altera".equals(act))
				{
				String step= req.getParameter("step");
				if(step==null)
					{
					req.setAttribute("assemblies",Assembly.getAssemblies());
					req.setAttribute("mpanels",factory.getMPanel().getValues());
					RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/altera-snp-form.jsp");
					dispatcher.forward(req, resp);
					return;
					}
					
				Altera altera= new Altera();
				
				altera.setFactory(factory);
				
				String s= req.getParameter("as");
				if(s==null) throw new ServletException("assembly missing");
				if(Cast.Integer.isA(s))
					{
					Assembly ably=Assembly.getAssemblyById(Cast.Integer.cast(s));
					if(ably==null) throw new ServletException("bad assembly");
					altera.setAssembly(ably);
					}
				
				s= req.getParameter("chrom");
				if(s==null) throw new ServletException("chrom missing");
				altera.setChromosome(s);
				
				s= req.getParameter("start");
				if(!Cast.UInteger.isA(s))  throw new ServletException("bad start");
				altera.setStart(Cast.UInteger.cast(s));
				
				s= req.getParameter("end");
				if(!Cast.UInteger.isA(s))  throw new ServletException("bad end");
				altera.setEnd(Cast.UInteger.cast(s));
				
				s= req.getParameter("filterflags");
				if(s==null) s="";
				altera.setFilterFlags(s);
				
				/* get panels */
				Set<MPanel> mpanels= new HashSet<MPanel>();
				
				for(String m:arrayNotNull(req.getParameterValues("mpanel")))
					{
					if(!Cast.UInteger.isA(m)) continue;
					MPanel mPanel= factory.getMPanel().get(Cast.UInteger.cast(m));
					if(mPanel!=null) mpanels.add(mPanel);
					}
					
				altera.setMPanels(mpanels);
				
				s= req.getParameter("minsnpconfidence");
				if(Cast.UInteger.isA(s))
					{
					//TODO
					//altera.setStart(Cast.UInteger.cast(s));
					}
				
				
				altera.preprocess();
				if("text".equals(req.getParameter("fmt")))
					{
					resp.addHeader( "Content-Disposition", "attachment; filename="+ Ymd.now()+"_snpmap.xls" ) ;
					resp.setContentType("application/vnd.ms-excel");
					altera.print(resp.getWriter());
					}
				else if("svg".equals(req.getParameter("fmt")))
					{
					req.setAttribute("chrom", altera.getChromosome());
					req.setAttribute("start", altera.getStart());
					req.setAttribute("end", altera.getEnd());
					req.setAttribute("factory", factory);
					req.setAttribute("assembly", altera.getAssembly());
					RequestDispatcher dispatcher = req.getRequestDispatcher("/map");
					dispatcher.forward(req, resp);
					}
				else
					{
					req.setAttribute("altera", altera);
					RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/altera-snp-html.jsp");
					dispatcher.forward(req, resp);
					}
				
				}
			else if("spindle-allele".equals(act))
				{
				List<PrjFin> prjfin4dnas= this.getPrjFinForUser(user, factory, PrjFin.Target.DNA);
				
					
				Spindle spindle= new Spindle();
				
				spindle.setFactory(factory);
				
				String s= req.getParameter("as");
				if(s==null) throw new ServletException("assembly missing");
				if(Cast.Integer.isA(s))
					{
					spindle.setAssembly(Assembly.getAssemblyById(Cast.Integer.cast(s)));
					}
				
				s= req.getParameter("chrom");
				if(s==null) throw new ServletException("chrom missing");
				spindle.setChromosome(req.getParameter("chrom"));
				
				s= req.getParameter("start");
				if(!Cast.UInteger.isA(s))  throw new ServletException("bad start");
				spindle.setStart(Cast.UInteger.cast(s));
				
				s= req.getParameter("end");
				if(!Cast.UInteger.isA(s))  throw new ServletException("bad end");
				spindle.setEnd(Cast.UInteger.cast(s));
				
				
				PrjFin prjfin=null;
				s= req.getParameter("prjfin4dna");
				if(s==null) throw new ServletException("prjfin4dna");
				for(PrjFin prj: prjfin4dnas)
					{
					if(prj.getProjCode().equals(s))
						{
						prjfin=prj;
						}
					}
				if(prjfin==null) throw new ServletException("forbidden prjfin4dna");
				spindle.setPrjFin(prjfin);
				
				
				PrjDna prjdna= factory.getPrjDna().get(prjfin.getProjCode());
				if(prjdna==null) throw new ServletException("prjdna Not Found");
				spindle.setPrjDna(prjdna);
				
				boolean by_column= req.getParameter("format").equals("column");
				
				
				resp.addHeader( "Content-Disposition", "attachment; filename="+ Ymd.now()+"_genotypes.xls" ) ;
				resp.setContentType("text/plain");
				if(by_column)
					{
					spindle.printByColumn(resp.getWriter());
					}
				else
					{
					spindle.printByRow(resp.getWriter());
					}
				}
			else if("search".equals(act))
				{
				String key= req.getParameter("key");
				if(key==null || key.trim().length()==0) throw new ServletException("search key missing");
				Set<Integer> tids= new HashSet<Integer>();
				Integer tid= factory.getUTerms().getTermId(key);
				if(tid!=null)
					{
					tids.add(tid);
					}
				else
					{
					tid= factory.getLTerms().getTermId(key);
					if(tid!=null)
						{
						tids.add(tid);
						}
					else
						{
						tids.addAll(factory.getEWords().getTermIds(key));
						}
					}
				req.setAttribute("tids", tids);
				RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/index.jsp");
				dispatcher.forward(req, resp);
				}
			else
				{	
				debug(act);
				RequestDispatcher dispatcher = req.getRequestDispatcher("WEB-INF/jsp/index.jsp");
				dispatcher.forward(req, resp);
				}
			}
		catch(DatabaseException err)
			{
			err.printStackTrace();
			throw new ServletException(err);
			}
		catch(IOException err)
			{
			throw err;
			}
		catch(Exception err)
			{
			err.printStackTrace();
			throw new ServletException(err);
			}
		finally
			{
			if(factory!=null) try { factory.close();} catch(Throwable err2) { err2.printStackTrace();}
			if(operon!=null) try { operon.close(); } catch(Throwable err2) { err2.printStackTrace();}
			}
		}
	
	
	
	
	

	
	
	
}
